#ifndef _IDNGRAM_MERGE_H_
#define _IDNGRAM_MERGE_H_

#include <stdio.h>
#include <map>
#include <vector>
#include <algorithm>

#include "idngram.h"
#include "fmerge.h"


template <int N>
void DoIdngramMerge(FILE *out, CMultiWayFileMerger<CIdngramFreq<N> > &merger)
{
  merger.start();
  CIdngramFreq<N> prevItem;

  while (true) {
    file_para<CIdngramFreq<N> > *ppara = merger.getBest();
    TUnitAndParaInfo<CIdngramFreq<N> > & upi = *(*ppara);
    if (upi.runOut) {
      if (prevItem.freq != 0) {
        fwrite(prevItem.ids, sizeof(TWORDID), N, out);
        fwrite(&(prevItem.freq), sizeof(unsigned int), 1 ,out);
      }
      break;
    }
    CIdngramFreq<N>& ng = upi.unit;
    if (!(prevItem == ng)) {
      if (prevItem.freq != 0) {
        fwrite(prevItem.ids, sizeof(TWORDID), N, out);
        fwrite(&(prevItem.freq), sizeof(unsigned int), 1 ,out);
      }
      prevItem = ng;
    } else {
      prevItem.freq += ng.freq; /* equal ids,so get rid of writing file! */
    }
    merger.next();
  }
}

/* Multi single swap files */
template<int N>
void ProcessingIdngramMerge(FILE *out, std::vector<FILE *>& file_list)
{
  CMultiWayFileMerger<CIdngramFreq<N> >merger;
  for (int i = 0; i < file_list.size(); ++i) {
    fseek(file_list[i], 0, SEEK_END);
    merger.addPara(file_list[i], 0, ftell(file_list[i]));
  }
}

/* single swap file */
template<int N>
void ProcessingIdngramMerge(FILE *swap, FILE *out, std::vector<long>& para_offsets)
{
  CMultiWayFileMerger<CIdngramFreq<N> > merger;
  long s = 0;
  for (int i = 0; i < para_offsets.size(); ++i) {
    merger.addPara(swap, s, para_offsets[i]);
    s = para_offsets[i];
  }
  DoIdngramMerge(out, merger);
}


#endif /* _IDNGRAM_MERGE_H_ */
